import os
import glob
import socket


class MOSS(object):

    allowed_languages = ["c", "cc", "java", "ml", "pascal", "ada", "lisp", "scheme", "haskell", "fortran", "ascii", "vhdl", "perl", "matlab", "python", "mips", "prolog", "spice", "vb", "csharp", "modula2", "a8086", "javascript", "plsql", "verilog"];
    options = {}
    basefiles = []
    files = []
    server = ""
    port = 7690
    userid = ""

    def __init__(self):
        server = "moss.stanford.edu"
        port = 7690
        self.options['m'] = 10
        self.options['d'] = 0
        self.options['n'] = 250
        self.options['x'] = 0
        self.options['c'] = ""
        self.options['l'] = "c"
        self.server = server
        self.port = port
        self.userid = "286208522"
        return

    def setLanguage(self, lang):
        if lang in self.allowed_languages:
            self.options['l'] = lang
            return True
        else:
            raise Exception("Unsupported language", 1)


    def getAllowedLanguages(self):
        return self.allowed_languages

    def is_bool(self,enabled):
        if(type(enabled)=="bool"):
            return True


    def setDirectoryMode(self,enabled):
        if (isinstance(enabled,bool)):
            self.options['d'] = int(enabled)
            return True
        else:
            raise Exception("DirectoryMode must be a boolean", 2)

    def addBaseFile(self,file):
        if (os.path.exists(file) and os.access(file, os.R_OK)):
            self.basefiles.append(file)
            return True
        else:
            raise Exception("Can't find or read the basefile ("+file+")", 3)


    def setIngoreLimit(self,limit):
        if (isinstance(limit,int) and limit > 1):
            self.options['m'] = int(limit)
            return True

        else:
            raise Exception("The limit needs to be greater than 1", 4)

    def setCommentString(self,comment):
        self.options['c'] = comment
        return True

    def setResultLimit(self,limit):
        if (isinstance(limit,int) and limit > 1):
            self.options['n'] = int(limit)
            return True
        else:
            raise Exception("The limit needs to be greater than 1", 5)
    def setExperimentalServer(self,enabled):
        if (isinstance(enabled)):
            self.options['x'] = int(enabled)
            return True
        else:
            raise Exception("Needs to be a boolean", 6)
    def addFile(self,file):

        if (os.path.exists(file) and os.access(file, os.R_OK)):
            self.files.append(file)

            return True
        else:

            raise Exception("Can't find or read the file ("+file+")", 7)

    def addByWildcard(self,path):
        for file in glob.glob(path):
            print file
            self.addFile(file)

    def send(self):

        address = (self.server,self.port)
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect(address)
        s.send("moss "+str(self.userid)+"\n"+"directory "+str(self.options['d'])+"\n"+"X "+str(self.options['x'])+"\n"+"maxmatches "+str(self.options['m'])+"\n"+"show "+str(self.options['n'])+"\n"+"language "+str(self.options['l'])+"\n")

        read = s.recv(512)

        print read
        if read == "no":
            s.send("end\n")
            s.close()
            raise Exception("Unsupported language", 1)
        for bfile in self.basefiles:
            self.uploadFile(s,bfile,0)
            print bfile
        i = 1

        for file in self.files:
            self.uploadFile(s, file, i)
            i+=1

        s.send("query 0 "+self.options['c']+"\n")
        read = s.recv(512)
        s.send("end\n")
        s.close()
        return read


    def uploadFile(self,handle, file, id):
        size = os.path.getsize(file)
        file_name_fixed = os.path.basename(file).replace(" ","_")
        handle.send("file "+str(id)+" "+str(self.options['l'])+" "+str(size)+" "+str(file_name_fixed)+"\n")

        file = open(file)
        handle.send(file.read())